#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <sys/sysinfo.h>
#include <net/if.h>
#include <linux/if_packet.h>
#include <unistd.h>

#define DEBUGP(fmt, ...) printf("%s(%d): "fmt"\n", __func__, __LINE__, ##__VA_ARGS__)

typedef struct pcap_file_header {
	unsigned int magic;
	unsigned short version_major;
	unsigned short version_minor;
	unsigned int thiszone;    
	unsigned int sigfigs;   
	unsigned int snaplen;   
	unsigned int linktype;  
} pcap_file_header_t;

typedef struct timestamp {
	unsigned int timestamp_s;
	unsigned int timestamp_ms;
} timestamp_t;
 
typedef struct pcap_header{
	struct timestamp ts;
	unsigned int capture_len;
	unsigned int len;
} pcap_header_t;

char ifname[32] = {0};

static int send_pkt(void * pkt, int len)
{
	static int fd = -1;
	static struct sockaddr_ll addr;

	if (fd == -1) {
		fd = socket(PF_PACKET, SOCK_RAW, 0x0);
		if (fd < 0) {
			perror("socket");
			goto exit;
		}

		memset(&addr, 0, sizeof(addr));
		addr.sll_family = PF_PACKET;
		addr.sll_ifindex = if_nametoindex((ifname[0]?ifname:"br-lan"));
		if (addr.sll_ifindex == 0) {
			goto fail;
		}
	}

	if (sendto(fd, pkt, len, 0,
				(struct sockaddr *)&addr, sizeof(struct sockaddr_ll)) <= 0) {
		perror("send");
		goto fail;
	}

exit:
	return 0;

fail:
	if (fd >= 0) {
		close(fd);
		fd = -1;
	}
	return 0;
}

void rs_pkt(char * file_name)
{
	FILE * fp = NULL;
	char buf[2048] = {0};
	struct pcap_file_header pfh;
	struct pcap_header ph;
	int count = 0;
	//int skip_count = 800;
	//int skip_count = 1000;
	int skip_count = 1218;
	int skip_last = 220;
	int send_count = 0;
	long long int pkt_len = 0;

	fp = fopen(file_name, "r");
	if (fp == NULL) {
		perror("fopen");
		goto exit;
	}

	if (fread(&pfh, sizeof(pfh), 1, fp) <= 0) {
		perror("fread pfh");
		goto exit;
	}

	DEBUGP("pfh, magic: %0x, ver: %u:%u, zone: %d, sig: %d, snap: %d, link: %d",
			pfh.magic, pfh.version_major, pfh.version_minor, pfh.thiszone, 
			pfh.sigfigs, pfh.snaplen, pfh.linktype);
	while(1) {

		if (fread(&ph, sizeof(ph), 1, fp) <= 0) {
			//perror("fread ph");
			goto exit;
		}

		memset(buf, 0, sizeof(buf));
		if (fread(&buf, 1, ph.capture_len, fp) != ph.capture_len) {
			perror("fread buf");
			goto exit;
		}

		count++;
		//skip_count = 1218;
		// tcp
		//skip_count = 166;
		//skip_count = 736;

		//skip_count = 352;
		skip_count = 0;
		if (skip_count > 0) {
			if (count < skip_count) {
				continue;
			}
		}

		//skip_last = 220;
		skip_last = 0;
		if (skip_last > 0) {
			if ((1687 - count) < skip_last) {
				continue;
			}
		}

		DEBUGP("ph[%04d], tm: %d.%d, cap_len: %d, len: %d",
				count, ph.ts.timestamp_s, ph.ts.timestamp_ms, ph.capture_len, ph.len);
#if 1
		send_pkt(buf, ph.capture_len);
		pkt_len += ph.capture_len;
#else
		while (1) {
			usleep(1);
			send_pkt(buf, ph.capture_len);
		}
#endif
		send_count ++;

		if (feof(fp)) { 
			break;
		}
	}

exit:
	if (fp) {
		fclose(fp);
	}
	DEBUGP("count: %d, skip: %d, pkt_len: %llu, skip_last: %d, send_count: %d",
			count, skip_count, pkt_len, skip_last, send_count);
	return;
}

int main(int argc, char *argv[])
{
	char buf[2048] = {0};
	struct pcap_file_header pfh;
	struct pcap_header ph;
	char file[128] = {0};
	
	if (argc == 2) {
		strncpy(file, argv[1], sizeof(file));
	} else if (argc == 3) {
		strncpy(file, argv[1], sizeof(file));
		strncpy(ifname, argv[2], sizeof(ifname));
	} else {
		printf("%s [file] [ifname]\n");
		return 0;
	}

	while (1) {
		usleep(100);
		rs_pkt(file);
	}

	return 0;
}
